using Sage.WindowsProcess.Configuration;
using Sage.WindowsProcess.Events;
using Sage.WindowsProcess.Models;
using System.Runtime.Versioning;

namespace Sage.WindowsProcess.Services
{
    /// <summary>
    /// 进程管理服务接口
    /// </summary>
    public interface IProcessManagerService : IDisposable, IAsyncDisposable
    {
        /// <summary>
        /// 获取所有已配置的进程键
        /// </summary>
        IEnumerable<string> GetAllKeys();

        /// <summary>
        /// 获取指定键的配置
        /// </summary>
        ProcessConfig? GetConfig(string key);

        /// <summary>
        /// 启动所有已配置的进程
        /// </summary>
        /// <param name="timeout">等待进程启动的超时时间（毫秒）。指定0表示无限等待。默认为30000毫秒。</param>
        /// <returns>表示异步操作的任务</returns>
        [SupportedOSPlatform("windows")]
        Task StartAllAsync(int timeout = 30000);

        /// <summary>
        /// 启动指定键的进程
        /// </summary>
        /// <param name="key">进程键</param>
        /// <param name="timeout">等待进程启动的超时时间（毫秒）。指定0表示无限等待。默认为30000毫秒。</param>
        /// <returns>表示异步操作的任务，其结果指示进程是否成功启动</returns>
        [SupportedOSPlatform("windows")]
        Task<bool> StartAsync(string key, int timeout = 30000);

        /// <summary>
        /// 停止所有正在运行的进程
        /// </summary>
        /// <param name="timeout">等待进程退出的超时时间（毫秒）。指定0表示无限等待。默认为5000毫秒。</param>
        /// <returns>表示异步操作的任务</returns>
        Task StopAllAsync(int timeout = 5000);

        /// <summary>
        /// 停止指定键的进程
        /// </summary>
        /// <param name="key">进程键</param>
        /// <param name="timeout">等待进程退出的超时时间（毫秒）。指定0表示无限等待。默认为5000毫秒。</param>
        /// <returns>表示异步操作的任务，其结果指示进程是否成功停止</returns>
        Task<bool> StopAsync(string key, int timeout = 5000);

        /// <summary>
        /// 重启指定键的进程
        /// </summary>
        /// <param name="key">进程键</param>
        /// <param name="startTimeout">启动超时（毫秒）。默认为30000毫秒。</param>
        /// <param name="stopTimeout">停止超时（毫秒）。默认为5000毫秒。</param>
        /// <returns>表示异步操作的任务，其结果指示进程是否成功重启</returns>
        [SupportedOSPlatform("windows")]
        Task<bool> RestartAsync(string key, int startTimeout = 30000, int stopTimeout = 5000);

        /// <summary>
        /// 检查指定键的进程是否正在运行
        /// </summary>
        bool IsRunning(string key);

        /// <summary>
        /// 获取指定键的进程状态
        /// </summary>
        [SupportedOSPlatform("windows")]
        ProcessStatusInfo? GetStatus(string key);

        /// <summary>
        /// 设置指定进程的优先级
        /// </summary>
        /// <param name="key">进程键</param>
        /// <param name="priority">要设置的优先级</param>
        /// <returns>设置是否成功</returns>
        [SupportedOSPlatform("windows")]
        bool SetProcessPriority(string key, System.Diagnostics.ProcessPriorityClass priority);

        #region 后续版本弃用的方法
        /// <summary>
        /// 动态添加进程配置
        /// </summary>
        /// <param name="config">进程配置</param>
        /// <returns>添加是否成功</returns>
        /// <exception cref="ArgumentNullException">配置为空时抛出</exception>
        /// <exception cref="ArgumentException">配置缺少必要参数时抛出</exception>
        [Obsolete("方法将被弃用，请改用AddConfig", false)]
        bool AddProcess(ProcessConfig config);

        /// <summary>
        /// 动态添加多个进程配置
        /// </summary>
        /// <param name="configs">进程配置集合</param>
        /// <returns>添加是否成功</returns>
        /// <exception cref="ArgumentNullException">配置集合为空时抛出</exception>
        /// <exception cref="ArgumentException">配置缺少必要参数时抛出</exception>
        [Obsolete("方法将被弃用，请改用AddConfig", false)]
        bool AddProcesses(IEnumerable<ProcessConfig> configs);

        /// <summary>
        /// 移除进程配置并停止相关进程
        /// </summary>
        /// <param name="key">进程键</param>
        /// <param name="stopRunning">是否停止正在运行的进程</param>
        /// <returns>移除是否成功</returns>
        /// <remarks>如果stopRunning为true，将先尝试停止进程，然后再移除配置</remarks>
        [Obsolete("方法将被弃用，请改用RemoveConfigs", false)]
        Task<bool> RemoveProcessAsync(string key, bool stopRunning = true);
        #endregion

        /// <summary>
        /// 动态添加进程配置
        /// </summary>
        /// <param name="config">进程配置</param>
        /// <returns>添加是否成功</returns>
        /// <exception cref="ArgumentNullException">配置为空时抛出</exception>
        /// <exception cref="ArgumentException">配置缺少必要参数时抛出</exception>
        bool AddConfig(ProcessConfig config);

        /// <summary>
        /// 动态添加多个进程配置
        /// </summary>
        /// <param name="configs">进程配置集合</param>
        /// <returns>添加是否成功</returns>
        /// <exception cref="ArgumentNullException">配置集合为空时抛出</exception>
        /// <exception cref="ArgumentException">配置缺少必要参数时抛出</exception>
        bool AddConfig(IEnumerable<ProcessConfig> configs);

        /// <summary>
        /// 移除进程配置并停止相关进程
        /// </summary>
        /// <param name="key">进程键</param>
        /// <param name="stopRunning">是否停止正在运行的进程</param>
        /// <returns>移除是否成功</returns>
        /// <remarks>如果stopRunning为true，将先尝试停止进程，然后再移除配置</remarks>
        Task<bool> RemoveConfigAsync(string key, bool stopRunning = true);

        // 服务级事件
        /// <summary>
        /// 当任何进程产生输出时发生
        /// </summary>
        event EventHandler<ProcessServiceOutputEventArgs>? ProcessOutput;

        /// <summary>
        /// 当任何进程产生错误输出时发生
        /// </summary>
        event EventHandler<ProcessServiceOutputEventArgs>? ProcessError;

        /// <summary>
        /// 当任何进程启动时发生
        /// </summary>
        event EventHandler<ProcessServiceStartedEventArgs>? ProcessStarted;

        /// <summary>
        /// 当任何进程退出时发生
        /// </summary>
        event EventHandler<ProcessServiceExitedEventArgs>? ProcessExited;

        /// <summary>
        /// 当进程管理服务产生错误时发生
        /// </summary>
        event EventHandler<ProcessServiceErrorEventArgs>? ProcessServiceError;

        /// <summary>
        /// 当任何进程状态更新时发生
        /// </summary>
        event EventHandler<ProcessServiceStatusEventArgs>? ProcessStatusUpdated;

        /// <summary>
        /// 向指定进程的标准输入写入数据
        /// </summary>
        /// <param name="key">进程键</param>
        /// <param name="input">要写入的输入字符串</param>
        /// <param name="cancellationToken">可用于取消操作的取消令牌</param>
        /// <returns>表示异步操作的任务，其结果指示数据是否成功写入</returns>
        ValueTask<bool> WriteToStandardInputAsync(string key, string input, CancellationToken cancellationToken = default);

        /// <summary>
        /// 等待指定进程退出
        /// </summary>
        /// <param name="key">进程标识符</param>
        /// <param name="timeout">等待超时时间（毫秒），-1表示无限等待</param>
        /// <param name="cancellationToken">取消令牌</param>
        /// <returns>如果进程成功退出则返回true，否则返回false</returns>
        Task<bool> WaitForExitAsync(string key, int timeout = -1, CancellationToken cancellationToken = default);
    }
}
